#include "stdafx.h"
#include "debt.h"
#include "julianDate.h"

//#define DEBUG

CDebt::CDebt()
{
    CDebt("",0.0,0.0);
}

CDebt::CDebt(std::string name, long double principal, double rate)
: CMoney(name, principal, rate)
 , m_numPeriods(1)
 , m_numCompounds(12)
 
{
    m_values.resize(m_numPeriods);
    for(int i = 0; i < m_numPeriods; i++)
        m_values[i] = m_principal / m_numPeriods;
}

CDebt::~CDebt()
{
    
}

void CDebt::refresh()
{
    m_values.resize(m_numPeriods);
    for(int i = 0; i < m_numPeriods; i++)
        m_values[i] = m_principal / m_numPeriods;
    m_minPayment = compound(m_numCompounds,m_numPeriods)/(m_numPeriods * m_numCompounds);
#ifdef DEBUG
    std::cout << "Minimum Payment = " << m_minPayment << std::endl;
#endif
    m_amortized.resize(m_values.size());
    m_interest.resize(m_values.size());
    CDebt temp=*this;
    for(int i = 0; i < m_interest.size(); i++)
    {
        m_interest[i] = temp.getTotal() *  m_rate;
#ifdef DEBUG
        std::cout << "Interest " << i << " = " << m_interest[i] << std::endl;
#endif
        m_amortized[i] = m_interest[i] + m_minPayment;
#ifdef DEBUG
        std::cout << "Amortized " << i << " = " << m_amortized[i] << std::endl;
#endif
        temp.makePayment(m_minPayment);
    }
}

void CDebt::print()
{
    refresh();
    sDate date = convertJulianToDate(m_payOffDate);
    std::cout<<"Debt Name: " << m_name << std::endl
        << "Rate: " << m_rate << std::endl
        << "Start Date: " << asctime(localtime(&m_startDate)) << std::endl
        << "End Date: " << asctime(localtime(&m_endDate)) << std::endl
        << "Total Debt Remaining: " << getTotal() << std::endl
        << "Pay Off Date: " << (int)date.month << "/" << (int)date.day << "/" << (int)date.year << std::endl
        << "Total Amortized: " << totalAmortized() << std::endl
        << "Total Interest: " << totalInterest() << std::endl;
}

double CDebt::makePayment(double payment)
{
    if(m_values.size() > 0)
    {
        if(payment > m_values[0])
        {
            // Over pay remove from end
            double leftover = payment - m_values[0];
#ifdef DEBUG
            std::cout << "Leftover = " << leftover << std::endl;
#endif
            if(m_values.erase(m_values.begin()) != m_values.end())
            {
                while(leftover > 0.0)
                {
                    leftover -= *m_values.end();
#ifdef DEBUG
                    std::cout << "Leftover = " << leftover << std::endl;
#endif
                    if(leftover < 0.0)
                    {
                        m_values[m_values.size() - 1] = -leftover;
#ifdef DEBUG
                        std::cout << "Last Val = " << *m_values.end()  << std::endl;
#endif
                    }
                    else
                    {
                        m_values.pop_back();
                    }
                }
            }
            return leftover;
        }
        else if(payment == m_values[0])
        {
            // Standard pay remove current
            if(m_values.erase(m_values.begin()) != m_values.end())
                return 0;
            return -1;
        }
        else
        {
            // Underpay add to front
            m_values[0] -= payment;
        }
        return 0.0;
    }
}

double CDebt::totalAmortized()
{
    return std::accumulate(m_amortized.begin(), m_amortized.end(), 0);
}

double CDebt::totalInterest()
{
    return std::accumulate(m_interest.begin(), m_interest.end(), 0);
}

double CDebt::compound(unsigned short numCompounds, unsigned short numPeriods)
{
    double comp = getTotal() * pow(1 + (0.01 * m_rate)/(double)numCompounds, (double)numCompounds * (double)numPeriods);
#ifdef DEBUG
    std::cout << "    Total = " << getTotal() << std::endl
        << "   Compound = " << comp << std::endl;
#endif
    return comp;
}